/*
 * mysql_thread.h
 *
 *  Created on: 2013-12-19
 *      Author: lixingyi
 */

#ifndef MYSQL_THREAD_H_
#define MYSQL_THREAD_H_

#include <vector>
#include <string>
#include <signal.h>
#include <memory>

#include <boost/lockfree/queue.hpp>

#include "framework/thread.h"
#include "framework/circular_queue.h"

#include "libdrizzle-2.0/drizzle_client.h"
#include "libdrizzle-2.0/drizzle_server.h"


class MysqlConfig
{
public:

    MysqlConfig():m_id(0),m_port(0) {} ;

    const char* host() { return m_host.c_str(); } ;
    const char* username() { return m_username.c_str() ; } ;
    const char* password(){return m_password.c_str() ;} ;
    const char* dbname(){return m_dbname.c_str();} ;
    const char* charset() { return m_charset.c_str();} ;
    const int id() { return m_id ;} ;
    const int port() { return m_port ;} ;
    
    void reset(const char* host,const char* username,const char* password,
        const char* dbname,const char* charset,int id,int port=3306)
    {
        this->m_host=host ;
        this->m_username=username;
        this->m_password=password;
        this->m_dbname=dbname;
        this->m_charset=charset;
        this->m_id= id;
        this->m_port = port ;
    }

private:
    std::string m_host ;
    std::string m_username ;
    std::string m_password;
    std::string m_dbname ;
    std::string m_charset;
    int m_id ;
    int m_port ;

} ;


class ProxyThread ;
class DrizzleResponse ;

class DrizzleRequest
{
public:
    DrizzleRequest(std::shared_ptr<ProxyThread> source,
        const char* sql,int size,drizzle_command_t command):
        m_source(source),m_sql(sql,size),m_create_time(time(0)),m_command(command)
    {
    }
    
    ~DrizzleRequest() { } ;

    ProxyThread* source() { return m_source.get() ; } ;
    drizzle_command_t command() { return m_command ; } ;
    const char* sql() { return m_sql.c_str() ; } ;
    int create_time() { return m_create_time ;} ;
private:
    std::shared_ptr<ProxyThread> m_source ;
    std::string m_sql ;
    int m_create_time ;
    drizzle_command_t m_command ;
    
} ;


class MysqlThread: public kingnet::simple_thread
{

public:
    MysqlThread();
    virtual ~MysqlThread();

public:
    //should be called before thread start
    void set_args(const MysqlConfig& mysql_config) 
    {
        m_config = mysql_config ;
    }

    bool push_request(DrizzleRequest* request)
    {
        bool ret = m_request_queue.push(request) ;
        if(ret) pthread_cond_signal(&m_cond) ;
        return ret ;
    }
    
protected:
    virtual int on_init() ;
    virtual void on_fini() ;
    virtual void run_once() ;

    void on_timer() ;
    int on_request(DrizzleRequest* request,DrizzleResponse* response);

private:
    pthread_cond_t m_cond ;
    pthread_mutex_t m_mutex ;
    boost::lockfree::queue<DrizzleRequest*,boost::lockfree::capacity<2048> > m_request_queue ;
    drizzle_st* m_drizzle ;
    drizzle_con_st* m_conn ;
    drizzle_result_st m_result ;
    MysqlConfig m_config ;

    int m_last_time ;
    bool m_reload_flag ;


};

#endif /* DATA_THREAD_H_ */
